package com.ruoyi.canteen.service;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.canteen.domain.CanteenUser;
import com.ruoyi.canteen.mapper.CanteenUserMapper;
import com.ruoyi.canteen.service.impl.CanteenCpOrderServiceImpl;
import com.ruoyi.canteen.utils.JwtToken;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.text.MessageFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @Author Ryan
 * @Date 2021/9/19 16:53
 * @Version 1.0
 */
@Service
public class WxAuthenticationService {

    private static final Logger log = LoggerFactory.getLogger(WxAuthenticationService.class);
    @Autowired
    private ObjectMapper mapper;

    @Autowired
    private CanteenUserMapper userMapper;

    @Value("${wx.code2session}")
    private String code2SessionUrl;
    @Value("${qywx.code2session}")
    private String qyCode2SessionUrl;
    @Value("${qywx.accessToken}")
    private String qyAccessTokenUrl;


    @Value("${xcx.accessToken}")
    private String accessTokenUrl;

    @Value("${wx.appid}")
    private String appid;
    @Value("${wx.appsecret}")
    private String appsecret;


    @Value("${qywx.corpid}")
    private String corpid;
    @Value("${qywx.corpsecret}")
    private String corpsecret;

    @Value("${wecard.accessToken}")
    private String wecardTokenUrl;
    @Value("${wecard.appkey}")
    private String appkey;
    @Value("${wecard.appSecret}")
    private String appSecret;
    @Value("${wecard.userDetail}")
    private String userDetailUrl;


    /**
     * 普通微信code2Session
     * @param code
     * @return
     */
    public String code2Session(String code) {
        String url = MessageFormat.format(this.code2SessionUrl, this.appid, this.appsecret, code);
        RestTemplate rest = new RestTemplate();
        Map<String, Object> session = new HashMap<>();
        String sessionText = rest.getForObject(url, String.class);
        try {
            session = mapper.readValue(sessionText, Map.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return this.registerUser(session);
    }

    /**
     * 注册本地用户
     * @param session
     * @return
     */
    private String registerUser(Map<String, Object> session) {
        String openid = (String)session.get("openid");
        if (openid == null){
//            throw new ServiceException("获取微信 openid 为空");
            log.error("获取微信 openid 为空", session);
            return "";
        }
        CanteenUser user = userMapper.selectCanteenUserByOpenId(openid);
        if(user != null){
            // 已有用户信息
            return JwtToken.makeToken(user.getId());
        }
        // TODO 重复插入 nested exception is java.sql.SQLIntegrityConstraintViolationException:
        // Duplicate entry 'okSnj4j5krN20656s8iSeiZ2y5-w' for key 'canteen_user.uni_openid'
        // 新用户信息：
        CanteenUser newUser = new CanteenUser();
        newUser.setOpenid(openid);
        newUser.setUserType(Long.valueOf(1));
        newUser.setCreateTime(new Date());
        userMapper.insertCanteenUser(newUser);
        // TODO:返回JWT令牌
        Long uid = newUser.getId();
        return JwtToken.makeToken(uid);
    }

    /**
     * 获取企业微信token
     * @return
     */
    public Map getQyAccessToken() {
        String url = MessageFormat.format(this.qyAccessTokenUrl, this.corpid, this.corpsecret);
        RestTemplate rest = new RestTemplate();
        Map<String, Object> session = new HashMap<>();
        String sessionText = rest.getForObject(url, String.class);
        try {
            session = mapper.readValue(sessionText, Map.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return session;
    }

    /**
     * 企业微信code2Session
     * @param code
     * @return
     */
    public String getQyUserId(String token, String code) {
        String url = MessageFormat.format(this.qyCode2SessionUrl, token, code);
        RestTemplate rest = new RestTemplate();
        Map<String, Object> session = new HashMap<>();
        String sessionText = rest.getForObject(url, String.class);
        String userId = "";
        try {
            session = mapper.readValue(sessionText, Map.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        if(session.get("errcode").equals("0")){
            // 正常
            userId = session.get("userid").toString();
        }else{
            String errmsg = session.get("errmsg").toString();
        }
        return userId;
    }

    /**
      获取用户信息(通过企微接口)
     * @return
     */
    public String getUserInfoByQy(String accessToken, String userId){
        String getUserUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={0}&userid={1}";
        String url = MessageFormat.format(getUserUrl, accessToken, userId);
        RestTemplate rest = new RestTemplate();
        Map<String, Object> tokenMap = new HashMap<>();
        String sessionText = rest.getForObject(url, String.class);
        try {
            tokenMap = mapper.readValue(sessionText, Map.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return this.registerQyUserByQw(tokenMap);
    }

    /**
     * 微卡注册本地企业用户信息
     * @param session
     * @return
     */
    private String registerQyUserByQw(Map<String, Object> session) {
        String userId = (String)session.get("userId");
        if (userId == null){
            throw new ServiceException("获取微信 userId 为空");
        }
        CanteenUser user = userMapper.selectCanteenUserByUserCode(userId);
        if(user != null){
            // 已有用户信息
            return JwtToken.makeToken(user.getId());
        }else{
            // 新用户信息：
            CanteenUser newUser = new CanteenUser();
            newUser.setUserCode(userId);
            newUser.setNickname(session.get("name").toString());
            newUser.setMobile(session.get("mobile").toString());
            newUser.setWxProfile(session.get("avatar").toString());
            newUser.setUserType(Long.valueOf(2));
            newUser.setCreateTime(new Date());
            int result = userMapper.insertQyCanteenUser(newUser);
            if(result > 0){
                // 新增用户
                // TODO:返回JWT令牌
                Long uid = newUser.getId();
                return JwtToken.makeToken(uid);
            }else {
                // 用户已存在
                CanteenUser curUser = userMapper.selectCanteenUserByUserCode(userId);
                return JwtToken.makeToken(curUser.getId());
            }
        }
    }


    /**
     * 微卡获取token
     * @return
     */
    public Map getWeCardToken(String wxcode){
//        String postUrl = "https://tygate.weixiao.qq.com/connect/oauth2/token";
        String postUrl = wecardTokenUrl;
        RestTemplate restTemplate = new RestTemplate();

        JSONObject json = new JSONObject();
        json.put("wxcode", wxcode);
        json.put("app_key", appkey);
        json.put("app_secret", appSecret);
        json.put("grant_type", "authorization_code");
        json.put("redirect_uri", "mnp://wxec1f8a81fd304889");

        Map<String, Object> session = new HashMap<>();
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        HttpEntity<String> formEntity = new HttpEntity<String>(json.toString(), headers);
        try{
            log.info("postUrl:" + postUrl);
            log.info("formEntity:" + formEntity.toString());
            String sessionText = restTemplate.postForEntity(postUrl, formEntity, String.class).getBody();
            log.info("getWeCardToken:" + wxcode +";返回:" + sessionText);
            session = mapper.readValue(sessionText, Map.class);
        }catch (Exception ex){
            // TODO 400 Bad Request: [{"error_description":"Invalid code","error":"invalid_request"}]
            log.error(ex.toString());
        }
        return session;
    }

    /**
     * 微卡获取用户信息
     * @return
     */
    public String getWeCardUserInfo(String token){
//        String postUrl = "https://tygate.weixiao.qq.com/connect/oauth/get-user-info";
        String postUrl = userDetailUrl;
        RestTemplate restTemplate = new RestTemplate();

        JSONObject json = new JSONObject();
        json.put("access_token", token);

        Map<String, Object> session = new HashMap<>();
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        headers.setContentType(type);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
        HttpEntity<String> formEntity = new HttpEntity<String>(json.toString(), headers);
        try{
            String sessionText = restTemplate.postForEntity(postUrl, formEntity, String.class).getBody();
            session = mapper.readValue(sessionText, Map.class);
        }catch (Exception ex){
            log.error(ex.toString());
        }
        return this.registerQyUserByWk(session);
    }

    /**
     * 微卡注册本地企业用户信息
     * @param session
     * @return
     */
    private String registerQyUserByWk(Map<String, Object> session) {
        String card_number = (String)session.get("card_number");
        if (card_number == null){
            throw new ServiceException("获取微信 card_number 为空");
        }
        CanteenUser user = userMapper.selectCanteenUserByUserCode(card_number);
        if(user != null){
            // 已有用户信息,更新信息
//            user.setAuthCode(session.get("auth_code").toString());
            user.setMobile(session.get("telephone").toString());
            user.setUpdateTime(new Date());
            userMapper.updateCanteenUser(user);
            return JwtToken.makeToken(user.getId());
        }else{
            // 新用户信息：
            CanteenUser newUser = new CanteenUser();
            newUser.setUserCode(card_number);
//        newUser.setAuthCode(session.get("auth_code").toString());
            newUser.setNickname(session.get("name").toString());
            newUser.setMobile(session.get("telephone").toString());
            newUser.setWxProfile(session.get("head_image").toString());
            newUser.setUserType(Long.valueOf(2));
            newUser.setCreateTime(new Date());
//            userMapper.insertCanteenUser(newUser);
//            // TODO:返回JWT令牌
//            Long uid = newUser.getId();
//            return JwtToken.makeToken(uid);
            log.info("newUser 信息："+ newUser.toString());
            int result = -1;
            try{
                result = userMapper.insertQyCanteenUser(newUser);
            }catch (Exception ex){
                log.error("registerQyUserByWk 失败："+ ex.toString());
            }
            if(result > 0){
                // 新增用户
                // TODO:返回JWT令牌
                Long uid = newUser.getId();
                return JwtToken.makeToken(uid);
            }else {
                // 用户已存在
                CanteenUser curUser = userMapper.selectCanteenUserByUserCode(card_number);
                return JwtToken.makeToken(curUser.getId());
            }
        }

    }

}
